﻿#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

Scalar encode(int msg, bool is_binary)
{
    if (is_binary)
    {
        return msg ? Scalar(255, 255, 255) : Scalar(0, 0, 0);
    }

    switch (msg)
    {
    case 0:
        return Scalar(0, 0, 0);
    case 1:
        return Scalar(255, 255, 255);
    case 2:
        return Scalar(0, 0, 255);
    case 3:
        return Scalar(255, 0, 0);
    case 4:
        return Scalar(0, 255, 0);
    case 5:
        return Scalar(255, 0, 255);
    case 6:
        return Scalar(0, 255, 255);
    case 7:
        return Scalar(255, 255, 0);
    default:
        return Scalar(0, 0, 0);
    }
}

int decode(Scalar color, bool is_binary)
{
    if (is_binary)
    {
        return (color[0] + color[1] + color[2]) / 3 > 127 ? 1 : 0;
    }

    Mat rgb(1, 1, CV_8UC3, color);
    Mat hsv;
    cvtColor(rgb, hsv, COLOR_BGR2HSV);
    Vec3b v = hsv.at<Vec3b>(0, 0);

    if (v[2] < 50)
        return 0;
    if (v[2] > 200 && v[1] < 50)
        return 1;

    if (v[0] < 15)
        return 2;
    if (v[0] > 100 && v[0] < 135)
        return 3;
    if (v[0] > 35 && v[0] < 85)
        return 4;
    if (v[0] > 135 && v[0] < 165)
        return 5;
    if (v[0] > 15 && v[0] < 35)
        return 6;
    if (v[0] > 85 && v[0] < 100)
        return 7;

    return 0;
}

void send(int msg, bool mode)
{
    Mat img(480, 640, CV_8UC3, encode(msg, mode));
    namedWindow("TX", WINDOW_NORMAL);
    setWindowProperty("TX", WND_PROP_FULLSCREEN, WINDOW_FULLSCREEN);
    imshow("TX", img);
    waitKey(3000);
}

int receive(bool mode)
{
    VideoCapture cap(0);
    if (!cap.isOpened())
        return -1;

    Mat frame;
    cap >> frame;
    if (frame.empty())
        return -1;

    Rect roi(frame.cols / 2 - 50, frame.rows / 2 - 50, 100, 100);
    Scalar color = mean(frame(roi));

    imshow("RX", frame);
    waitKey(1000);

    return decode(color, mode);
}

int main()
{
    char role;
    cout << "发送端(T)还是接收端(R)? ";
    cin >> role;

    if (role == 'T' || role == 't')
    {
        int type, data;
        cout << "模式（0:二进 1:八进）: ";
        cin >> type;
        cout << "数据: ";
        cin >> data;
        send(data, type == 0);
    }
    else if (role == 'R' || role == 'r')
    {
        int type;
        cout << "模式（0:二进 1:八进）: ";
        cin >> type;
        int res = receive(type == 0);
        cout << "收到: " << res << endl;
    }

    destroyAllWindows();
    return 0;
}